FinanceTracker
A self-hosted personal finance tracker that turns monthly CommBank and Westpac CSV exports into an AI-categorised spending dashboard, on desktop and as an installable phone PWA, where privacy is a property of the architecture, not a promise.
One brain, two windows
One FastAPI backend owns all data and logic; the desktop dashboard and phone PWA are stateless views of it, served privately over Tailscale. The mandatory sanitiser runs before any network call and fails closed: if a row can't be confidently cleaned, it is dropped rather than risk sending it. The only payload that ever leaves is (row_index, cleaned_description, amount), and every outbound payload is written to a local audit log so it can be verified after the fact.
What leaves the machine
- ✗Never: account numbers, BSBs, card numbers, balances, names, references, memos: regex-scrubbed, every digit run removed
- ✗Never: CSV inputs, the SQLite database, Excel files, or logs into git: blocked by pre-commit hooks
- ✓Only: anonymous merchant-and-amount pairs to OpenRouter for categorisation: a stream that could belong to anyone
- ✓Only: the monthly Excel workbook to your own Google Drive, via a service account you control
F-01Content-based bank detection
Files are matched to a bank by their contents, not their upload slot: wrong-slot uploads still parse, unknown formats are rejected with a clear message.
F-02Idempotent pipeline
File and transaction fingerprinting make re-runs a no-op: no duplicate rows, no wasted categorisation calls, no changed output.
F-03Internal transfer netting
Money moved between own accounts is matched as opposite-sign pairs and excluded from totals, and from the categorisation payload entirely.
F-04Subscription watch
Recurring-merchant detection flags new subscriptions, price changes, and expected income that didn't arrive.
F-05Offline-tolerant phone PWA
Client-side queue-and-retry holds an upload made while the laptop is asleep and retries until it lands, privately, over Tailscale HTTPS.
F-06Always-on supervisor
A ~15 MB Windows service probes both servers every 15 s, relaunches whichever is down, and snapshots the database weekly via SQLite's online-backup API.
F-07Budget alerts, amount-free
Per-category budgets fire at 80% and 100%: alert payloads carry only a category name and a percent, never amounts or descriptions.
F-08Categoriser scorecard
A monthly accuracy card built from recategorisation events shows whether the LLM categoriser (swappable via config, with automatic fallback) improves over time.
The real thing is self-hosted: this is the demo
The actual app runs on your own machine, with your own keys, and the data never leaves your hardware. This demo is the same frontend, fed entirely by synthetic data: click every screen, flip the theme, run a search. Nothing here is real spending.
Open the live demo Source on GitHub